package edu.ynu.se.xiecheng.achitectureclass.service;

import edu.ynu.se.xiecheng.achitectureclass.common.service.LogicService;
import edu.ynu.se.xiecheng.achitectureclass.dao.SoilSensorDao;
import edu.ynu.se.xiecheng.achitectureclass.dto.SoilSensorDTO;
import edu.ynu.se.xiecheng.achitectureclass.entity.SoilSensor;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SoilSensorService extends LogicService<SoilSensorDao, SoilSensor, Long> {

    private String accessToken;
    private long tokenExpirationTime;
    private final String BOX_NO = "300023040198";
    private final String[] SENSOR_IDS = {
        "327061430532576246",
        "327061430532576250",
        "327061430532576242",
        "327061430532576243",
        "327061430532576244"
    };

    public SoilSensorService(@Autowired SoilSensorDao sensorDao) {
        super(sensorDao);
        try {
            refreshToken();
            // 启动时获取第一次数据
            System.out.println("应用启动，开始获取第一次土壤传感器数据...");
            refreshSoilSensorData();
        } catch (Exception e) {
            System.err.println("Error initializing SoilSensorService: " + e.getMessage());
        }
    }

    private List<SoilSensor> newData;

    public void getNewData() {
        try {
            // 构建请求体
            JSONObject requestBody = new JSONObject();
            JSONArray idsArray = new JSONArray();
            for (String id : SENSOR_IDS) {
                idsArray.put(id);
            }
            requestBody.put("ids", idsArray);

            // 创建 HttpHeaders 对象
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setBearerAuth(accessToken);

            // 创建 HttpEntity 对象
            HttpEntity<String> entity = new HttpEntity<>(requestBody.toString(), headers);

            // 发送 POST 请求并获取响应
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> response = restTemplate.postForEntity(
                "https://fbox360.com/api/v2/dmon/value/get?boxNo=" + BOX_NO, 
                entity, 
                String.class
            );

            if (response.getStatusCode().is2xxSuccessful()) {
                newData = parseSensors(response.getBody());
                System.out.println("成功获取 " + (newData != null ? newData.size() : 0) + " 条传感器数据");
            } else {
                System.err.println("获取传感器数据失败，状态码: " + response.getStatusCodeValue());
                newData = new ArrayList<>();
            }
        } catch (Exception e) {
            System.err.println("获取传感器数据时发生错误: " + e.getMessage());
            e.printStackTrace();
            newData = new ArrayList<>();
        }
    }

    private void refreshToken() {
        String newAccessToken = getAccessToken();
        if (newAccessToken != null) {
            accessToken = newAccessToken;
            tokenExpirationTime = System.currentTimeMillis() + (2 * 60 * 60 * 1000); // 2 小时后过期
            System.out.println("Token refreshed successfully");
        } else {
            System.err.println("Failed to refresh token");
            // 可以在这里添加重试逻辑或其他错误处理
        }
    }

    @Scheduled(fixedRate = 7200000) // 每 2 小时刷新一次
    private void scheduledRefreshToken() {
        refreshToken();
    }

    private String getAccessToken() {
        String tokenUrl = "https://fbox360.com/idserver/core/connect/token";
        String grantType = "client_credentials";
        String clientId = "68db2e8bda8d47b5b5db7eaf71c7dcdd";
        String clientSecret = "76dc724c95004acab25482d344dab407";
        String scope = "fbox";

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("grant_type", grantType);
        requestBody.add("client_id", clientId);
        requestBody.add("client_secret", clientSecret);
        requestBody.add("scope", scope);

        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(requestBody, headers);

        try {
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> response = restTemplate.postForEntity(tokenUrl, entity, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                JSONObject jsonResponse = new JSONObject(response.getBody());
                String accessToken = jsonResponse.getString("access_token");
                System.out.println("New access token: " + accessToken);
                return accessToken;
            } else {
                System.out.println("Failed to get access token, status code: " + response.getStatusCodeValue());
                return null;
            }
        } catch (Exception e) {
            System.err.println("Error getting access token: " + e.getMessage());
            return null;
        }
    }

    @Scheduled(fixedRate = 300000) // 每 5 分钟执行一次
    public void refreshSoilSensorData() {
        try {
            System.out.println("开始定时获取土壤传感器数据: " + new Date());
            
            // 检查token是否过期
            if (System.currentTimeMillis() >= tokenExpirationTime) {
                System.out.println("Token已过期，正在刷新...");
                refreshToken();
            }
            
            boolean success = refreshData();
            if (success) {
                System.out.println("成功获取并保存土壤传感器数据");
            } else {
                System.out.println("获取土壤传感器数据失败或无新数据");
            }
        } catch (Exception e) {
            System.err.println("定时获取土壤传感器数据时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public Boolean refreshData() {
        try {
            getNewData();
            if (newData == null || newData.isEmpty()) {
                System.out.println("没有新的传感器数据");
                return false;
            }
            
            // 打印详细的数据信息
            System.out.println("===== 土壤传感器数据详情 =====");
            for (SoilSensor sensor : newData) {
                System.out.println(String.format(
                    "传感器: %s, 值: %d, 时间: %s, 状态: %d, 连接状态: %d",
                    sensor.getName(),
                    sensor.getValue(),
                    sensor.getTimestamp(),
                    sensor.getStatus(),
                    sensor.getConnState()
                ));
            }
            System.out.println("============================");
            
            // 保存数据
            getDAO().saveAll(newData);
            System.out.println("成功保存 " + newData.size() + " 条传感器数据到数据库");
            return true;
        } catch (Exception e) {
            System.err.println("刷新数据时发生错误: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    public List<SoilSensorDTO> getAllSoilSensorsDTO() {
        List<SoilSensor> sensors = getDAO().findAll();
        return sensors.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    private SoilSensorDTO convertToDTO(SoilSensor sensor) {
        SoilSensorDTO sensorDTO = new SoilSensorDTO();
        sensorDTO.setId(sensor.getId());
        sensorDTO.setTimestamp(sensor.getTimestamp());
        sensorDTO.setDataType(sensor.getDataType());
        sensorDTO.setName(sensor.getName());
        sensorDTO.setValue(sensor.getValue());
        sensorDTO.setBoxId(sensor.getBoxId());
        sensorDTO.setStatus(sensor.getStatus());
        sensorDTO.setConnState(sensor.getConnState());
        sensorDTO.setConnStateTimestamp(sensor.getConnStateTimestamp());
        return sensorDTO;
    }

    private static List<SoilSensor> parseSensors(String responseBody) {
        List<SoilSensor> sensorList = new ArrayList<>();
        try {
            JSONArray jsonArray = new JSONArray(responseBody);
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject sensorJson = jsonArray.getJSONObject(i);
                SoilSensor sensor = new SoilSensor();

                sensor.setTimestamp(parseDate(sensorJson.getString("timestamp")));
                sensor.setDataType(sensorJson.getInt("dataType"));
                sensor.setName(sensorJson.getString("name"));
                sensor.setValue(sensorJson.getInt("value"));
                sensor.setBoxId(sensorJson.getString("boxId"));
                sensor.setStatus(sensorJson.getInt("status"));
                sensor.setConnState(sensorJson.getInt("connState"));
                sensor.setConnStateTimestamp(parseDate(sensorJson.getString("connStateTimestamp")));

                sensorList.add(sensor);
            }
        } catch (Exception e) {
            return new ArrayList<>();
        }
        return sensorList;
    }

    private static Date parseDate(String dateStr) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'");
        return dateFormat.parse(dateStr);
    }

    /**
     * 获取每种类型传感器的最新数据
     * @return 每种传感器的最新数据DTO列表
     */
    public List<SoilSensorDTO> getLatestDataForEachSensor() {
        try {
            List<SoilSensor> latestSensors = getDAO().findLatestDataForEachSensor();
            
            // 转换为DTO并打印日志
            List<SoilSensorDTO> result = latestSensors.stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());
            
            // 打印详细的数据信息
            if (!result.isEmpty()) {
                System.out.println("===== 各类传感器最新数据 =====");
                for (SoilSensorDTO sensor : result) {
                    System.out.println(String.format(
                        "传感器: %s, 值: %d, 时间: %s, 状态: %d, 连接状态: %d",
                        sensor.getName(),
                        sensor.getValue(),
                        sensor.getTimestamp(),
                        sensor.getStatus(),
                        sensor.getConnState()
                    ));
                }
                System.out.println("============================");
            } else {
                System.out.println("没有找到任何传感器数据");
            }
            
            return result;
        } catch (Exception e) {
            System.err.println("获取最新传感器数据时发生错误: " + e.getMessage());
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    public List<SoilSensorDTO> getSoilMoistureHistory() {
        return getDAO().findAllSoilMoisture().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public List<SoilSensorDTO> getSoilTemperatureHistory() {
        return getDAO().findAllSoilTemperature().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public List<SoilSensorDTO> getSoilNitrogenHistory() {
        return getDAO().findAllSoilNitrogen().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public List<SoilSensorDTO> getSoilPhosphorusHistory() {
        return getDAO().findAllSoilPhosphorus().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public List<SoilSensorDTO> getSoilPotassiumHistory() {
        return getDAO().findAllSoilPotassium().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
}

